import LXCOM from '../common/common.js'
import baseunitgrah from './baseunitgrah.js'
import { CoordTRFUtil } from '../common/tools/coordtool.js'
import Coord from '../common/struct/coord.js'
import ActPkg from '../graph/action/ellipseaction.js'
import UtilFuncs from '../common/tools/utilfuncs.js'
var funcs = UtilFuncs.UtilFuncs;

import GlobalConst from '../common/globalConst.js'
var global = GlobalConst.GlobalConst;
import { FillUtil } from '../graph/paintutil/fillutil.js'
import { Strokeutil } from '../graph/paintutil/strokeutil.js'


import { LGXEnums } from '../common/sysenum.js'
import { CommonPaintUtil } from './paintutil/compaintutil.js'
import { GlobalVar } from '../common/globalvar.js'
import { LGXMathTool } from '../common/tools/math/lgxmathtool.js'

import ellipse from '../common/struct/basestruct/ellipse.js'
var ellipseUnit = ellipse.Ellipse;

class EllipseGraph extends baseunitgrah.BaseUnitGraph {
    constructor(type) {
        super(type);
        this.m_graphType = LGXEnums.LGXGraphType.EllipseGraph_type;
        var p = new Coord.EllipsePos();
        this.setPos(p);
        var action = new ActPkg.EllipseGraphAction(this);
        this.setActionSvc(action);
    }

    display(map, mapInfo, forClip) {
        var postion = this.getPosCopy();
        var scaling = mapInfo.getLenthDisScale();
        var disRadius = scaling * postion.yRadius;
        var disLongRadius = scaling * postion.xRadius;
        var x = postion.x;
        var y = postion.y;
        var cntpt = { x, y };
        var p1 = CoordTRFUtil.world2Screen(cntpt, mapInfo);

        var cntWorldPT = this.getZone().getCnt();
        var cntScreenPT = CoordTRFUtil.world2Screen(cntWorldPT, mapInfo);
        let rotv = this.getRadAngle();

        map.save();
        map.translate(cntScreenPT.x, cntScreenPT.y);
        map.rotate(-rotv);
        map.scale(this.localScale.x, this.localScale.y);
        map.translate(-cntScreenPT.x, -cntScreenPT.y);
        map.beginPath();
        map.ellipse(p1.x, p1.y, disLongRadius, disRadius, 0, 0, Math.PI * 2, false);
        map.closePath();
        map.restore();

        map.save();
        if (!forClip) {
            Strokeutil.active(this._lineDef, this, map, mapInfo);
            FillUtil.active(this._fillDef, map, this, mapInfo, false);
        }

        super.displayGraphScope(map, mapInfo);
        this.displayFeaturePoint(map, mapInfo);
        if (this._highLight) {
            CommonPaintUtil.disPointCross(cntpt, GlobalVar.highlightColor.toHexString(), map, mapInfo);
        }
        map.restore();
    }

    displayFeaturePoint(map, mapInfo) {
        if (mapInfo.paintForGenerateICON) {
            return;
        }

        if (this._selected) {
            super.displayFeaturePoint(map, mapInfo);
            this.displayControlPoint(map, mapInfo);
        }
        else if (this.m_pContainer && this.m_pContainer._selected) {
            this.displayControlPoint(map, mapInfo);
        }
    }

    disInSymbol(transformInfo, map, mapInfo, forClip) {
        var postion = this.getPosCopy();
        var lenthDisScale = mapInfo.getLenthDisScale();

        var disXRadius = postion.xRadius * lenthDisScale * transformInfo.sx;
        var disYRadius = postion.yRadius * lenthDisScale * transformInfo.sy;

        let rotv = this.getRadAngle() + transformInfo.rotRad;
        let wpt = CoordTRFUtil.transLocalPt2World(postion, 0, transformInfo);
        let cntScreenPT = CoordTRFUtil.world2Screen(wpt, mapInfo);
        map.save();
        map.translate(cntScreenPT.x, cntScreenPT.y);
        map.rotate(-rotv);
        map.scale(this.localScale.x, this.localScale.y);
        map.translate(-cntScreenPT.x, -cntScreenPT.y);
        map.beginPath();
        map.ellipse(cntScreenPT.x, cntScreenPT.y, disXRadius, disYRadius, 0, 0, Math.PI * 2, false);
        map.closePath();

        if (!forClip) {
            Strokeutil.active(this._lineDef, this, map, mapInfo);
            FillUtil.active(this._fillDef, map, this, mapInfo, true, transformInfo);
        }
        map.restore();

    }

    distance(mousePoint, scaling, mapscale) {
        if (!super.preCheckInScope(mousePoint, scaling)) {
            return -1;
        }
        var cmpGap = super.getSelCmpGap(scaling, mapscale);
        var dis = -1;
        var position = this.getPosCopy();
        let interPt = this.chkPtOnEllipseArc(position,mousePoint, null);
        if (interPt) {
            dis = funcs.distancePoint(interPt,mousePoint,scaling);
            if (dis > cmpGap){
                dis = -1;
            }
        }
        return dis;
    }

    calculateSubKind(mousePoint, scaling, mapscale) {
        var nRefKind = 0;
        var cmpGap = super.getSelCmpGap(scaling, mapscale);

        var ptlst = this.getFeaturePtLst();
        //先检查当前鼠标位置是否足够临近特征点
        for (var i = 0; i < ptlst.length; i++) {
            var pt = ptlst[i];
            var lRst = funcs.distancePoint(pt, mousePoint, scaling);
            if ((lRst <= cmpGap) && (lRst >= 0)) {
                nRefKind = i + 1;
                mousePoint.clone(pt);
            }
        }

        if (nRefKind != 0) {
            return nRefKind;
        }
        let dis = this.distance(mousePoint, scaling, mapscale);
        if (dis >= 0){
            nRefKind = 10;
        }
        return nRefKind;
    }

    calculateSubControlPoint(mousePoint, scaling, mapscale) {
        let nRefKind = 0;
        let cmpGap = global.FocusSelGap;
        let ptlst = this.getControlPtLst();
        for (let i = 0; i < ptlst.length; i++) {
            let ctrlPt = ptlst[i];
            let dis = funcs.distancePoint({ x: ctrlPt.x, y: ctrlPt.y }, mousePoint, scaling);
            if ((dis <= cmpGap) && (dis >= 0)) {
                nRefKind = LGXEnums.LGXModGraphKind.CommonStSelKind + ctrlPt.kind;
                mousePoint.clone(ctrlPt);
            }
        }

        return nRefKind;
    }

    displayControlPoint(map, mapInfo) {
        let ptlst = this.getFeaturePtLst();
        for (let i = 0; i < ptlst.length; i++) {
            let ctrlPt = ptlst[i];
            var pt = CoordTRFUtil.world2Screen(ctrlPt, mapInfo);
            super.drawFocusPoint(map, pt.x, pt.y, "#ff00ff");
        }
    }

    calScope(mapscale) {
        var postion = this.getPosCopy();
        this._zone.left = (postion.x - postion.xRadius);
        this._zone.bottom = (postion.y - postion.yRadius);
        this._zone.right = (postion.x + postion.xRadius);
        this._zone.top = (postion.y + postion.yRadius);

        let ptlst = [];
        ptlst.push(this._zone.ltPt());
        ptlst.push(this._zone.lbPt());
        ptlst.push(this._zone.rtPt());
        ptlst.push(this._zone.rbPt());

        let rotAngle = this.getRadAngle();
        ptlst.forEach(pt => {
            let t = funcs.rotate(pt,postion,rotAngle);
            pt.x = t.x;
            pt.y = t.y;
        });
        this._zone.clone(funcs.calPtListZone(ptlst));
    }

    getLocalZone() {
        let rect = new LXCOM.LGXRect(0, 0, 0, 0);
        var postion = this.getPos();
        rect.left = (- postion.xRadius);
        rect.bottom = (- postion.yRadius);
        rect.right = (postion.xRadius);
        rect.top = (postion.yRadius);
        return rect;
    }

    getFeaturePtLst() {
        var postion = this.getPosCopy();
        var ptlst = new Array;

        var p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y - postion.yRadius;
        ptlst.push(p);

        p = new LXCOM.LGXPoint();
        p.x = postion.x - postion.xRadius;
        p.y = postion.y;
        ptlst.push(p);

        p = new LXCOM.LGXPoint();
        p.x = postion.x + postion.xRadius;
        p.y = postion.y;
        ptlst.push(p);

        p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y + postion.yRadius;
        ptlst.push(p);

        p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y;
        ptlst.push(p);

        let rotAngle = this.getRadAngle();
        ptlst.forEach(pt => {
            let t = funcs.rotate(pt,postion,rotAngle);
            pt.x = t.x;
            pt.y = t.y;
        });

        return ptlst;
    }

    getControlPtLst() {
        var postion = this.getPos();
        var ptlst = new Array;

        let x = postion.x + postion.xRadius;
        let y = postion.y;
        let ctrlPt = { kind: 6, x, y };
        ptlst.push(ctrlPt);

        x = postion.x;
        y = postion.y + postion.yRadius;
        ctrlPt = { kind: 5, x, y };
        ptlst.push(ctrlPt);
        return ptlst;
    }

    getDimDatumFeatureLst() {
        let rstArr = [];

        let idkey = 1;

        let position = this.getPos();
        //图形中心
        {
            let data = { x: position.x, y: position.y };
            let info = { type: LGXEnums.DimDatumType.center, data, id: idkey++ };
            rstArr.push(info);
        }

        let idxVal = 0;
        //顶点特征
        let x = position.x;
        let y = position.y + position.yRadius;
        let data = { idx: idxVal++, x, y };
        let info = { type: LGXEnums.DimDatumType.vertex, data, id: idkey++ };
        rstArr.push(info);

        x = position.x + position.xRadius;
        y = position.y;
        data = { idx: idxVal++, x, y };
        info = { type: LGXEnums.DimDatumType.vertex, data, id: idkey++ };
        rstArr.push(info);

        x = position.x;
        y = position.y - position.yRadius;
        data = { idx: idxVal++, x, y };
        info = { type: LGXEnums.DimDatumType.vertex, data, id: idkey++ };
        rstArr.push(info);

        x = position.x - position.xRadius;
        y = position.y;
        data = { idx: idxVal++, x, y };
        info = { type: LGXEnums.DimDatumType.vertex, data, id: idkey++ };
        rstArr.push(info);
        return rstArr;
    }

    movePosOffset(tOffset, modCmdInfo) {
        if (this._selKind < 1) {
            return;
        }
        var nRefKind = this._selKind;
        var pCirclePos = this.getPosCopy();

        if (nRefKind > 0 && nRefKind < 5) {
            var selPos = new LXCOM.LGXPoint();
            if (nRefKind == 1) {
                selPos.x = pCirclePos.x;
                selPos.y = pCirclePos.y - pCirclePos.yRadius;
            }
            else if (nRefKind == 2) {
                selPos.x = pCirclePos.x - pCirclePos.xRadius;
                selPos.y = pCirclePos.y;
            }
            else if (nRefKind == 3) {
                selPos.x = pCirclePos.x + pCirclePos.xRadius;
                selPos.y = pCirclePos.y;
            }
            else if (nRefKind == 4) {
                selPos.x = pCirclePos.x;
                selPos.y = pCirclePos.y + pCirclePos.yRadius;
            }

            var nNewRefPosX = (selPos.x + tOffset.x);
            var nNewRefPosY = (selPos.y + tOffset.y);
            this.distortModify(nNewRefPosX, nNewRefPosY);

            selPos.x += tOffset.x;
            selPos.y += tOffset.y;
        }
        else {
            this.translate(tOffset, modCmdInfo.mapscale, false);
        }
    }

    distortModify(nNewRefPosX, nNewRefPosY) {
        var pCirclePos = this.getPos();
        switch (this._selKind) {
            case 1:
            case 4:
                pCirclePos.yRadius = Math.abs(nNewRefPosY - pCirclePos.y);
                break;

            case 2:
            case 3:
                pCirclePos.xRadius = Math.abs(nNewRefPosX - pCirclePos.x);
                break;

            default:
                break;
        }
    }

    getMainFeaturePTLst(tFeaturePTLst, transformInfo) {
        var postion = this.getPosCopy();
        let worldCnt = this.convertPt2World(postion, transformInfo);

        var p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y - postion.yRadius;
        tFeaturePTLst.push({ pt: p, kind: LGXEnums.AuxPointKind.end });

        p = new LXCOM.LGXPoint();
        p.x = postion.x - postion.xRadius;
        p.y = postion.y;
        tFeaturePTLst.push({ pt: p, kind: LGXEnums.AuxPointKind.end });

        p = new LXCOM.LGXPoint();
        p.x = postion.x + postion.xRadius;
        p.y = postion.y;
        tFeaturePTLst.push({ pt: p, kind: LGXEnums.AuxPointKind.end });

        p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y + postion.yRadius;
        tFeaturePTLst.push({ pt: p, kind: LGXEnums.AuxPointKind.end });

        p = new LXCOM.LGXPoint();
        p.x = postion.x;
        p.y = postion.y;
        tFeaturePTLst.push({ pt: p, kind: LGXEnums.AuxPointKind.center });

        let rotAngle = this.getRadAngle();
        if (transformInfo) {
            rotAngle += transformInfo.rotRad;
        }
        tFeaturePTLst.forEach(ele => {
            let pt = ele.pt;
            let t = funcs.rotate(pt, worldCnt, rotAngle);
            pt.x = t.x;
            pt.y = t.y;
        });
        return;
    }

    getSubFeaturePTLst(tFeaturePTLst, mousePoint, transformInfo) {
        let position = this.getPosCopy();
        let interPt = this.chkPtOnEllipseArc(position,mousePoint, transformInfo);
        if (interPt) {
            tFeaturePTLst.push({ pt: interPt, kind: LGXEnums.AuxPointKind.commonPt });
        }
    }

    assignInfo(info) {
        super.assignInfo(info);
        if (!this._position.xRadius) {
            this.setUseful(0);
        }
    }

    modifyAttribute(info, mapscale) {
        super.modifyAttribute(info, mapscale);
        this.calScope(mapscale);
    }

    toInfo() {
        var info = new ellipseUnit();
        this.toInfo4InheritClass(info);
        info.xRadius = this._position.xRadius;
        info.yRadius = this._position.yRadius;
        info.x = this._position.x;
        info.y = this._position.y;
        return info;
    }

    modifyCoord(propName, propVal, mapscale) {
        var position = this.getPos();
        if (propName == "cnt") {
            position.x = parseFloat(propVal.x);
            position.y = parseFloat(propVal.y);
        }
        else if (propName == "xRadius") {
            position.xRadius = parseFloat(propVal);
        }
        else if (propName == "yRadius") {
            position.yRadius = parseFloat(propVal);
        }
        this.notifyToObserver();
        this.calScope(mapscale);
    }

    getCoordInfo() {
        let graphPropDef = this.getCoordPropDef();
        let tableData = [];
        var position = this.getPosCopy();
        let x = position.x;
        let y = position.y;
        let cntObj = {
            propName: 'cnt',
            propLabel: '圆心',
            propValue: { x, y }
        };
        tableData.push(cntObj);

        let radisObj = {
            propName: 'xRadius',
            propLabel: '长轴',
            propValue: position.xRadius
        };
        tableData.push(radisObj);

        let radisLongObj = {
            propName: 'yRadius',
            propLabel: '短轴',
            propValue: position.yRadius
        };
        tableData.push(radisLongObj);

        let tableForm = {
            'tableData': tableData
        };
        return { graphPropDef, tableForm };
    }

    getCoordPropDef() {
        let graphPropDef = {
            cnt: {
                vtype: global.Pt_CoordType,
                range: { min: 1, max: 300 },
            },
            xRadius: {
                vtype: global.Single_CoordType,
                range: { min: 1, max: 300 },
            },
            yRadius: {
                vtype: global.Single_CoordType,
                range: { min: 1, max: 300 },
            }
        }
        return graphPropDef;
    }

    getPosCopy() {
        let pos = new Coord.EllipsePos();
        pos.clone(this._position);
        return pos;
    }

    onChgDimValue(dimGraph, oldValue, newValue) {
        console.log("rect graph onChgDimValue******");
        let svc = new CircleDimChg(this);
        svc.onChgDimValue(dimGraph, oldValue, newValue);
    }

    onDimBaseChged(dimGraph) {
        console.log("rect onDimBaseChged******");
        let svc = new CircleDimBaseChange(this);
        svc.onBaseChanged(dimGraph);
    }

    getLocalOrigin() {
        let pt = { x: 0, y: 0 };
        pt.x = this._position.x;
        pt.y = this._position.y;
        return pt;
    }

    clipFillZone_ex(map, mapInfo, transformInfo) {
        map.clip();
        var postion = this.getPosCopy();
        var scaling = mapInfo.getScaling();
        var disRadius = scaling * postion.yRadius;
        var disLongRadius = scaling * postion.xRadius;
        var p1 = CoordTRFUtil.world2Screen(postion, mapInfo);

        var cntWorldPT = this.getZone().getCnt();
        var cntScreenPT = CoordTRFUtil.world2Screen(cntWorldPT, mapInfo);
        let rotv = this.getRadAngle();

        map.save();
        map.translate(cntScreenPT.x, cntScreenPT.y);
        map.rotate(-rotv);
        map.scale(this.localScale.x, this.localScale.y);
        map.translate(-cntScreenPT.x, -cntScreenPT.y);
        map.beginPath();
        map.ellipse(p1.x, p1.y, disLongRadius, disRadius, 0, 0, Math.PI * 2, false);
        map.closePath();
        return 1;
    }

    chkPtOnEllipseArc(position,mousePoint, transformInfo) {
        let cnt = position.getCnt();
        let worldCnt = this.convertPt2World(cnt, transformInfo);
        position.x = 0;
        position.y = 0;

        let rotAngle = this.getRadAngle();
        if (transformInfo) {
            rotAngle += transformInfo.rotRad;
        }
        let localMtx = LGXMathTool.calLocalMatrix(worldCnt, funcs.radian2Degree(rotAngle));
        let localMtxInvert = localMtx.Inverse();
        let mousePtProj2Local = localMtxInvert.MultT({ x: mousePoint.x, y: mousePoint.y, z: 0 });
        let interPtList = funcs.getLineInterEllipseArc(mousePtProj2Local, { x: 0, y: 0 }, position);
        if (!interPtList || (interPtList && interPtList.length == 0)) {
            return null;
        }

        let local2WorldPt = null;
        if (interPtList.length == 1) {
            let pt = interPtList[0];
            local2WorldPt = localMtx.MultT({ x: pt.x, y: pt.y, z: 0 });
        }
        else if (interPtList.length == 2) {
            let pt0 = interPtList[0];
            let pt1 = interPtList[1];
            let dis0 = funcs.distancePoint(pt0, mousePtProj2Local, 1);
            let dis1 = funcs.distancePoint(pt1, mousePtProj2Local, 1);
            let dstPt = pt0;
            if (dis1 < dis0) {
                dstPt = pt1;
            }
            local2WorldPt = localMtx.MultT({ x: dstPt.x, y: dstPt.y, z: 0 });
        }
        return local2WorldPt;
    }

    setAngle(v) {
        this._angle = v;
        this._position.rotDegree = v;
    }

    //复制粘贴时，从复制源对象复制属性到本图形对应属性----虚函数，由实体继承类实现
    copySubPropFromBuf(bufInfo,tx,ty){
        this.copyCommnonPropFromBuf(bufInfo,tx,ty);
    }
}

export default { EllipseGraph }
